package io.finer.erp.jeecg.bas.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CacheConstant;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.MaterialConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.oConvertUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;

import io.finer.erp.jeecg.bas.dto.BasMaterialCategoryDTO;
import io.finer.erp.jeecg.bas.entity.BasCategoryLabel;
import io.finer.erp.jeecg.bas.entity.BasMaterialCategory;
import io.finer.erp.jeecg.bas.entity.BasProportion;
import io.finer.erp.jeecg.bas.entity.ZzShoporder;
import io.finer.erp.jeecg.bas.mapper.BasMaterialCategoryMapper;
import io.finer.erp.jeecg.bas.service.IBasCategoryLabelService;
import io.finer.erp.jeecg.bas.service.IBasMaterialCategoryService;
import io.finer.erp.jeecg.bas.service.IBasProportionService;
import io.finer.erp.jeecg.bas.service.IZzShoporderService;
import io.finer.erp.jeecg.stock.util.ScanUtil;

/**
 * @Description: 物料分类
 * @Author: jeecg-boot
 * @Date:   2020-05-29
 * @Version: V1.0
 */
@Service
public class BasMaterialCategoryServiceImpl extends ServiceImpl<BasMaterialCategoryMapper, BasMaterialCategory> implements IBasMaterialCategoryService {

	@Autowired
	private IBasProportionService proportionService;
	@Autowired
	private IZzShoporderService zzShopOrderService;
	@Autowired
	private BasMaterialCategoryMapper basMaterialCategoryMapper;
	@Autowired
	private IBasCategoryLabelService labelService;
	
	@Override
	@Cacheable(value = CacheConstant.BAS_MATERIAL_CATEGORY)
	public void addBasMaterialCategory(BasMaterialCategory basMaterialCategory) {
		if(oConvertUtils.isEmpty(basMaterialCategory.getPid())){
			basMaterialCategory.setPid(IBasMaterialCategoryService.ROOT_PID_VALUE);
		}else{
			//如果当前节点父ID不为空 则设置父节点的hasChildren 为1
			BasMaterialCategory parent = baseMapper.selectById(basMaterialCategory.getPid());
			if(parent!=null && !"1".equals(parent.getHasChild())){
				parent.setHasChild("1");
				baseMapper.updateById(parent);
			}
		}
		baseMapper.insert(basMaterialCategory);
	}
	
	@Override
	@Cacheable(value = CacheConstant.BAS_MATERIAL_CATEGORY)
	public void updateBasMaterialCategory(BasMaterialCategory basMaterialCategory) {
		BasMaterialCategory entity = this.getById(basMaterialCategory.getId());
		if(entity==null) {
			throw new JeecgBootException("未找到对应实体");
		}
		String old_pid = entity.getPid();
		String new_pid = basMaterialCategory.getPid();
		if(!old_pid.equals(new_pid)) {
			updateOldParentNode(old_pid);
			if(oConvertUtils.isEmpty(new_pid)){
				basMaterialCategory.setPid(IBasMaterialCategoryService.ROOT_PID_VALUE);
			}
			if(!IBasMaterialCategoryService.ROOT_PID_VALUE.equals(basMaterialCategory.getPid())) {
				baseMapper.updateTreeNodeStatus(basMaterialCategory.getPid(), IBasMaterialCategoryService.HASCHILD);
			}
		}
		baseMapper.updateById(basMaterialCategory);
	}
	
	@Override
	public void deleteBasMaterialCategory(String id) throws JeecgBootException {
		BasMaterialCategory basMaterialCategory = this.getById(id);
		if(basMaterialCategory==null) {
			throw new JeecgBootException("未找到对应实体");
		}
		updateOldParentNode(basMaterialCategory.getPid());
		baseMapper.deleteById(id);
	}

	/**
	 * 根据所传pid查询旧的父级节点的子节点并修改相应状态值
	 * @param pid
	 */
	private void updateOldParentNode(String pid) {
		if(!IBasMaterialCategoryService.ROOT_PID_VALUE.equals(pid)) {
			Integer count = baseMapper.selectCount(new QueryWrapper<BasMaterialCategory>().eq("pid", pid));
			if(count==null || count<=1) {
				baseMapper.updateTreeNodeStatus(pid, IBasMaterialCategoryService.NOCHILD);
			}
		}
	}
	
	public BasMaterialCategory getRootCategory(String id) {
		List<BasMaterialCategory> list = this.baseMapper.getRootCategory(id);
		if(null != list && 0 != list.size()) {
			return list.get(0);
		}
		return null;
	}

	@Override
	public List<BasMaterialCategory> getChildCategory(String rootId) {
		// TODO Auto-generated method stub
		return this.baseMapper.getChildCategory(rootId);
	}

	@Override
	public Result<?> getBCPCategory() {
		List<BasMaterialCategory> list = this.getChildCategoryByName("半成品");
		if(null != list && 0 != list.size()) {
			return Result.ok(list);
		}
		return Result.error("没有查询到结果");
	}

	@Override
	public Result<?> getCPCategory() {
		List<BasMaterialCategory> list = this.getChildCategoryByName("自有产品");
		if(null != list && 0 != list.size()) {
			return Result.ok(list);
		}
		return Result.error("没有查询到结果");
	}
	
	@Override
	public Result<?> getCengPinCategory() {
		List<BasMaterialCategory> list = this.getChildCategoryByName("成品");
		if(null != list && 0 != list.size()) {
			return Result.ok(list);
		}
		return Result.error("没有查询到结果");
	}

	private List<BasMaterialCategory> getChildCategoryByName(String name){
		LambdaQueryWrapper<BasMaterialCategory> query = new LambdaQueryWrapper<>();
		query.eq(BasMaterialCategory::getName, name);
		List<BasMaterialCategory> list = this.list(query);
		
		if(null != list && 0 != list.size()) {
			BasMaterialCategory one = list.get(0);
			String rootId = one.getId();
			List<BasMaterialCategory> resultList = this.baseMapper.getAllChildCategory(rootId);
			
			return resultList;
		}
		return null;
	}

	@Override
	public Result<?> getMaterialCategory(boolean childFlag) {
		List<BasMaterialCategory> categoryList = null;
		if(childFlag) {
			categoryList = this.baseMapper.getAllChildCategory(MaterialConstant.CATEGORY_YCL_ID);
		} else {
			categoryList = this.baseMapper.getAllChildCategoryHasChild(MaterialConstant.CATEGORY_YCL_ID);
		}
		return Result.ok(categoryList);
	}

	@Override
	public String getCategoryRoot(String id) {
		BasMaterialCategory rootCategory = this.getRootCategory(id);
		if(null != rootCategory) {
			if(MaterialConstant.CATEGORY_BCP_ID.equals(rootCategory.getId())) {
				return "BCP";
			}
			if(MaterialConstant.CATEGORY_CP_ID.equals(rootCategory.getId())) {
				return "CP";
			}
			if(MaterialConstant.CATEGORY_YCL_ID.equals(rootCategory.getId())) {
				return "YCL";
			}
			if(MaterialConstant.CATEGORY_ZYCP_ID.equals(rootCategory.getId())) {
				return "ZYCP";
			}
		}
		return null;
	}
	
	/**
	 * @Description 根据比重吨转平方
	 * @param qty
	 * @param categoryId
	 * @return
	 * Create at: 2020-09-23 17:41:57
	 * @author: duanyong
	 * Revision:
	 *    2020-09-23 17:41:57 - first revision by duanyong
	 *        
	 */
	public BigDecimal getSquare(BigDecimal qty, String categoryId) {
		BigDecimal square = BigDecimal.ZERO;
		LambdaQueryWrapper<BasProportion> proportionQuery = new LambdaQueryWrapper<>();
		proportionQuery.eq(BasProportion::getCatagroyId, categoryId);
		BasProportion basProportion = this.proportionService.getOne(proportionQuery);
		if (null == basProportion) {
			return square;
		}
		BigDecimal proportion = basProportion.getProportion();
		BigDecimal thickness = basProportion.getThickness();
		BigDecimal gramWeight = basProportion.getGramWeight();
		if(null == gramWeight || BigDecimal.ZERO.compareTo(gramWeight) >= 0) {
			square = qty.multiply(new BigDecimal(1000000)).divide(proportion, 4, BigDecimal.ROUND_DOWN).divide(thickness, 4, BigDecimal.ROUND_DOWN);
			square = square.setScale(4, BigDecimal.ROUND_DOWN);
		} else {
			square = qty.multiply(new BigDecimal(1000000)).divide(gramWeight, 4, BigDecimal.ROUND_DOWN);
			square = square.setScale(4, BigDecimal.ROUND_DOWN);
		}
		return square;
	}
	
	/**
	 * @Description 根据平方转吨
	 * @param square 平方
	 * @param categoryId 物料分类ID
	 * @return
	 * Create at: 2020-10-22 10:47:19
	 * @author: duany
	 * Revision:
	 *    2020-10-22 10:47:19 - first revision by duany
	 *        
	 */
	@Override
	public BigDecimal getTon(BigDecimal square, String categoryId) {
		LambdaQueryWrapper<BasProportion> proportionQuery = new LambdaQueryWrapper<>();
		proportionQuery.eq(BasProportion::getCatagroyId, categoryId);
		BasProportion basProportion = this.proportionService.getOne(proportionQuery);
		BigDecimal ton = BigDecimal.ZERO;
		if (null == basProportion) {
			return ton;
		}
		BigDecimal proportion = basProportion.getProportion();
		BigDecimal thickness = basProportion.getThickness();
		BigDecimal gramWeight = basProportion.getGramWeight();
		if(null == gramWeight || BigDecimal.ZERO.compareTo(gramWeight) >= 0) {
			ton = square.multiply(thickness).multiply(proportion).divide(new BigDecimal(1000000), 4, BigDecimal.ROUND_DOWN);
			ton = ton.setScale(4, BigDecimal.ROUND_DOWN);
		} else {
			ton = ton.multiply(gramWeight).divide(new BigDecimal(1000000), 4, BigDecimal.ROUND_DOWN);
			ton = ton.setScale(2, BigDecimal.ROUND_DOWN);
		}
		return ton;
	}

	@Override
	public BasMaterialCategory getCPCategory(String id) {
		BasMaterialCategory category = getById(id);
		String pid = this.getCategoryRoot(id);
		if(CommonConstant.CP_CATEGORY_ID.equals(pid)) {
			return category;
		}
		String code = category.getCode();
		String cpCode = "CP-" + code;
		BasMaterialCategory result = getByCode(cpCode);
//		if(null == result) {
//			result = new BasMaterialCategory();
//			result.setCode(cpCode);
//			result.setCreateBy("admin");
//			result.setCreateTime(org.jeecg.common.util.DateUtils.getDate());
//			result.setName(category.getName());
//			result.setIsEnabled(1);
//			result.setModel(category.getModel());
//			result.setSupplierId(category.getSupplierId());
//			result.setUnitId(category.getUnitId());
//			result.setVersion(1);
//			result.setPid(CommonConstant.CP_CATEGORY_ID);
//			this.save(result);
//		}
		return result;
	}
	
	private BasMaterialCategory getByCode(String code) {
		LambdaQueryWrapper<BasMaterialCategory> query = new LambdaQueryWrapper<>();
		query.eq(BasMaterialCategory::getCode, code);
		List<BasMaterialCategory> list = list(query);
		if(null != list && 0 != list.size()) {
			return list.get(0);
		}
		return null;
	}

	@Override
	public Result<?> getCategory() {
		List<BasMaterialCategory> list = Lists.newArrayList();
		List<BasMaterialCategory> list1 = this.getChildCategoryByName("成品");
		if(null != list1) {
			list.addAll(list1);
		}
		List<BasMaterialCategory> list2 = this.getChildCategoryByName("半成品");
		if(null != list2) {
			list.addAll(list2);
		}
		List<BasMaterialCategory> list3 = this.getChildCategoryByName("原材料");
		if(null != list3) {
			list.addAll(list3);
		}
		return Result.ok(list);
	}

	@Override
	public Result<?> getOrderCategory(String orderId) {
		if(StringUtils.isBlank(orderId)) {
			return Result.error("请填写订单信息!");
		}
		String[] ids = StringUtils.split(orderId, ",");
		List<String> idList = Arrays.asList(ids);
		LambdaQueryWrapper<ZzShoporder> query = new LambdaQueryWrapper<>();
		query.in(ZzShoporder::getId, idList);
		List<ZzShoporder> list = this.zzShopOrderService.list(query);
		if(null == list || list.size() == 0) {
			return Result.ok(new ArrayList<BasMaterialCategory>());
		}
		List<String> noList = Lists.newArrayList();
		for (ZzShoporder order : list) {
			String categoryId = order.getCategoryId();
			noList.add(categoryId);
		}
//		LambdaQueryWrapper<BasMaterialCategory> cateQuery = new LambdaQueryWrapper<>();
//		cateQuery.in(BasMaterialCategory::getId, noList);
//		List<BasMaterialCategory> cateList = list(cateQuery);
		List<BasMaterialCategoryDTO> cateList = basMaterialCategoryMapper.getBasMaterialCategoryDTO(noList);
		if(null == cateList || cateList.size() == 0) {
			return Result.ok(new ArrayList<BasMaterialCategoryDTO>());
		}
		return Result.ok(cateList);
	}

	@Override
	public Result<?> getGlueCategory() {
		BasMaterialCategory rootCate = this.lambdaQuery().eq(BasMaterialCategory::getName, "胶水").one();
		if(null != rootCate) {
			List<BasMaterialCategory> childCategory = this.getChildCategory(rootCate.getId());
			return Result.ok(childCategory);
		} else {
			return Result.error("未找到胶水物料分类。");
		}
	}
	
	@Override
	@Cacheable(value=CacheConstant.BAS_MATERIAL_CATEGORY)
	public Result<?> getCategoryName() {
		List<BasMaterialCategory> basMaterialCategoryList = this.list();
		basMaterialCategoryList = ScanUtil.changeListToVector(basMaterialCategoryList);
		return Result.ok(basMaterialCategoryList);
	}

	@Override
	public Result<List<BasCategoryLabel>> getCategoryLabel(String categoryId) {
		Result<List<BasCategoryLabel>> result = new Result<>();
		List<BasCategoryLabel> list = labelService.listByCategory(categoryId);
		result.setResult(list);
		result.setSuccess(Boolean.TRUE);
		result.setCode(CommonConstant.SC_OK_200);
		return result;
	}
}
